/*
 * Ext JS Library 0.20 Copyright(c) 2006-2008, Ext JS, LLC. licensing@extjs.com
 * 
 * http://extjs.com/license
 */

/*
 * Ext JS Library 2.0.1 Copyright(c) 2006-2008, Ext JS, LLC. licensing@extjs.com
 * 
 * http://extjs.com/license
 */

Ext.namespace('Ext.air', 'Ext.sql');

Ext.Template.prototype.compile = function() {
	var fm = Ext.util.Format;
	var useF = this.disableFormats !== true;

	var prevOffset = 0;
	var arr = [];
	var tpl = this;
	var fn = function(m, name, format, args, offset, s) {
		if (prevOffset != offset) {
			var action = {
				type : 1,
				value : s.substr(prevOffset, offset - prevOffset)
			};
			arr.push(action);
		}
		prevOffset = offset + m.length;
		if (format && useF) {
			if (args) {
				var re = /^\s*['"](.*)["']\s*$/;
				args = args.split(/,(?=(?:[^"]*"[^"]*")*(?![^"]*"))/);
				for (var i = 0, len = args.length; i < len; i++) {
					args[i] = args[i].replace(re, "$1");
				}
				args = [''].concat(args);
			} else {
				args = [''];
			}
			if (format.substr(0, 5) != "this.") {
				var action = {
					type : 3,
					value : name,
					format : fm[format],
					args : args,
					scope : fm
				};
				arr.push(action);
			} else {
				var action = {
					type : 3,
					value : name,
					format : tpl[format.substr(5)],
					args : args,
					scope : tpl
				};
				arr.push(action);
			}
		} else {
			var action = {
				type : 2,
				value : name
			};
			arr.push(action);
		}
		return m;
	};

	var s = this.html.replace(this.re, fn);
	if (prevOffset != (s.length - 1)) {
		var action = {
			type : 1,
			value : s.substr(prevOffset, s.length - prevOffset)
		};
		arr.push(action);
	}

	this.compiled = function(values) {
		function applyValues(el) {
			switch (el.type) {
				case 1 :
					return el.value;
				case 2 :
					return (values[el.value] ? values[el.value] : '');
				default :
					el.args[0] = values[el.value];
					return el.format.apply(el.scope, el.args);
			}
		}
		return arr.map(applyValues).join('');
	}
	return this;
};

Ext.Template.prototype.call = function(fnName, value, allValues) {
	return this[fnName](value, allValues);
}

Ext.DomQuery = function() {
	var cache = {}, simpleCache = {}, valueCache = {};
	var nonSpace = /\S/;
	var trimRe = /^\s+|\s+$/g;
	var tplRe = /\{(\d+)\}/g;
	var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
	var tagTokenRe = /^(#)?([\w-\*]+)/;
	var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;

	function child(p, index) {
		var i = 0;
		var n = p.firstChild;
		while (n) {
			if (n.nodeType == 1) {
				if (++i == index) {
					return n;
				}
			}
			n = n.nextSibling;
		}
		return null;
	};

	function next(n) {
		while ((n = n.nextSibling) && n.nodeType != 1);
		return n;
	};

	function prev(n) {
		while ((n = n.previousSibling) && n.nodeType != 1);
		return n;
	};

	function children(d) {
		var n = d.firstChild, ni = -1;
		while (n) {
			var nx = n.nextSibling;
			if (n.nodeType == 3 && !nonSpace.test(n.nodeValue)) {
				d.removeChild(n);
			} else {
				n.nodeIndex = ++ni;
			}
			n = nx;
		}
		return this;
	};

	function byClassName(c, a, v) {
		if (!v) {
			return c;
		}
		var r = [], ri = -1, cn;
		for (var i = 0, ci; ci = c[i]; i++) {
			if ((' ' + ci.className + ' ').indexOf(v) != -1) {
				r[++ri] = ci;
			}
		}
		return r;
	};

	function attrValue(n, attr) {
		if (!n.tagName && typeof n.length != "undefined") {
			n = n[0];
		}
		if (!n) {
			return null;
		}
		if (attr == "for") {
			return n.htmlFor;
		}
		if (attr == "class" || attr == "className") {
			return n.className;
		}
		return n.getAttribute(attr) || n[attr];

	};

	function getNodes(ns, mode, tagName) {
		var result = [], ri = -1, cs;
		if (!ns) {
			return result;
		}
		tagName = tagName || "*";
		if (typeof ns.getElementsByTagName != "undefined") {
			ns = [ns];
		}
		if (!mode) {
			for (var i = 0, ni; ni = ns[i]; i++) {
				cs = ni.getElementsByTagName(tagName);
				for (var j = 0, ci; ci = cs[j]; j++) {
					result[++ri] = ci;
				}
			}
		} else if (mode == "/" || mode == ">") {
			var utag = tagName.toUpperCase();
			for (var i = 0, ni, cn; ni = ns[i]; i++) {
				cn = ni.children || ni.childNodes;
				for (var j = 0, cj; cj = cn[j]; j++) {
					if (cj.nodeName == utag || cj.nodeName == tagName
							|| tagName == '*') {
						result[++ri] = cj;
					}
				}
			}
		} else if (mode == "+") {
			var utag = tagName.toUpperCase();
			for (var i = 0, n; n = ns[i]; i++) {
				while ((n = n.nextSibling) && n.nodeType != 1);
				if (n
						&& (n.nodeName == utag || n.nodeName == tagName || tagName == '*')) {
					result[++ri] = n;
				}
			}
		} else if (mode == "~") {
			for (var i = 0, n; n = ns[i]; i++) {
				while ((n = n.nextSibling)
						&& (n.nodeType != 1 || (tagName == '*' || n.tagName
								.toLowerCase() != tagName)));
				if (n) {
					result[++ri] = n;
				}
			}
		}
		return result;
	};

	function concat(a, b) {
		if (b.slice) {
			return a.concat(b);
		}
		for (var i = 0, l = b.length; i < l; i++) {
			a[a.length] = b[i];
		}
		return a;
	}

	function byTag(cs, tagName) {
		if (cs.tagName || cs == document) {
			cs = [cs];
		}
		if (!tagName) {
			return cs;
		}
		var r = [], ri = -1;
		tagName = tagName.toLowerCase();
		for (var i = 0, ci; ci = cs[i]; i++) {
			if (ci.nodeType == 1 && ci.tagName.toLowerCase() == tagName) {
				r[++ri] = ci;
			}
		}
		return r;
	};

	function byId(cs, attr, id) {
		if (cs.tagName || cs == document) {
			cs = [cs];
		}
		if (!id) {
			return cs;
		}
		var r = [], ri = -1;
		for (var i = 0, ci; ci = cs[i]; i++) {
			if (ci && ci.id == id) {
				r[++ri] = ci;
				return r;
			}
		}
		return r;
	};

	function byAttribute(cs, attr, value, op, custom) {
		var r = [], ri = -1, st = custom == "{";
		var f = Ext.DomQuery.operators[op];
		for (var i = 0, ci; ci = cs[i]; i++) {
			var a;
			if (st) {
				a = Ext.DomQuery.getStyle(ci, attr);
			} else if (attr == "class" || attr == "className") {
				a = ci.className;
			} else if (attr == "for") {
				a = ci.htmlFor;
			} else if (attr == "href") {
				a = ci.getAttribute("href", 2);
			} else {
				a = ci.getAttribute(attr);
			}
			if ((f && f(a, value)) || (!f && a)) {
				r[++ri] = ci;
			}
		}
		return r;
	};

	function byPseudo(cs, name, value) {
		return Ext.DomQuery.pseudos[name](cs, value);
	};

	eval("var batch = 30803;");

	var key = 30803;

	function nodup(cs) {
		if (!cs) {
			return [];
		}
		var len = cs.length, c, i, r = cs, cj, ri = -1;
		if (!len || typeof cs.nodeType != "undefined" || len == 1) {
			return cs;
		}
		var d = ++key;
		cs[0]._nodup = d;
		for (i = 1; c = cs[i]; i++) {
			if (c._nodup != d) {
				c._nodup = d;
			} else {
				r = [];
				for (var j = 0; j < i; j++) {
					r[++ri] = cs[j];
				}
				for (j = i + 1; cj = cs[j]; j++) {
					if (cj._nodup != d) {
						cj._nodup = d;
						r[++ri] = cj;
					}
				}
				return r;
			}
		}
		return r;
	}

	function quickDiff(c1, c2) {
		var len1 = c1.length;
		if (!len1) {
			return c2;
		}
		var d = ++key;
		for (var i = 0; i < len1; i++) {
			c1[i]._qdiff = d;
		}
		var r = [];
		for (var i = 0, len = c2.length; i < len; i++) {
			if (c2[i]._qdiff != d) {
				r[r.length] = c2[i];
			}
		}
		return r;
	}

	function quickId(ns, mode, root, id) {
		if (ns == root) {
			var d = root.ownerDocument || root;
			return d.getElementById(id);
		}
		ns = getNodes(ns, mode, "*");
		return byId(ns, null, id);
	}

	function search(path, root, type) {
		type = type || "select";

		var n = root || document;

		var q = path, mode, lq;
		var tk = Ext.DomQuery.matchers;
		var tklen = tk.length;
		var mm;

		var lmode = q.match(modeRe);
		if (lmode && lmode[1]) {
			mode = lmode[1].replace(trimRe, "");
			q = q.replace(lmode[1], "");
		}
		while (path.substr(0, 1) == "/") {
			path = path.substr(1);
		}
		while (q && lq != q) {
			lq = q;
			var tm = q.match(tagTokenRe);
			if (type == "select") {
				if (tm) {
					if (tm[1] == "#") {
						n = quickId(n, mode, root, tm[2]);
					} else {
						n = getNodes(n, mode, tm[2]);
					}
					q = q.replace(tm[0], "");
				} else if (q.substr(0, 1) != '@') {
					n = getNodes(n, mode, "*");
				}
			} else {
				if (tm) {
					if (tm[1] == "#") {
						n = byId(n, null, tm[2]);
					} else {
						n = byTag(n, tm[2]);
					}
					q = q.replace(tm[0], "");
				}
			}
			while (!(mm = q.match(modeRe))) {
				var matched = false;
				for (var j = 0; j < tklen; j++) {
					var t = tk[j];
					var m = q.match(t.re);
					if (m) {
						switch (j) {
							case 0 :
								n = byClassName(n, null, " " + m[1] + " ");
								break;
							case 1 :
								n = byPseudo(n, m[1], m[2]);
								break;
							case 2 :
								n = byAttribute(n, m[2], m[4], m[3], m[1]);
								break;
							case 3 :
								n = byId(n, null, m[1]);
								break;
							case 4 :
								return {
									firstChild : {
										nodeValue : attrValue(n, m[1])
									}
								};

						}
						q = q.replace(m[0], "");
						matched = true;
						break;
					}
				}

				if (!matched) {
					throw 'Error parsing selector, parsing failed at "' + q
							+ '"';
				}
			}
			if (mm[1]) {
				mode = mm[1].replace(trimRe, "");
				q = q.replace(mm[1], "");
			}
		}
		return nodup(n);
	}

	return {
		getStyle : function(el, name) {
			return Ext.fly(el).getStyle(name);
		},

		compile : function(path, type) {
			return function(root) {
				return search(path, root, type);
			}
		},

		select : function(path, root, type) {
			if (!root || root == document) {
				root = document;
			}
			if (typeof root == "string") {
				root = document.getElementById(root);
			}
			var paths = path.split(",");
			var results = [];
			for (var i = 0, len = paths.length; i < len; i++) {
				var p = paths[i].replace(trimRe, "");
				if (!cache[p]) {
					cache[p] = Ext.DomQuery.compile(p);
					if (!cache[p]) {
						throw p + " is not a valid selector";
					}
				}
				var result = cache[p](root);
				if (result && result != document) {
					results = results.concat(result);
				}
			}
			if (paths.length > 1) {
				return nodup(results);
			}
			return results;
		},

		selectNode : function(path, root) {
			return Ext.DomQuery.select(path, root)[0];
		},

		selectValue : function(path, root, defaultValue) {
			path = path.replace(trimRe, "");
			if (!valueCache[path]) {
				valueCache[path] = Ext.DomQuery.compile(path, "select");
			}
			var n = valueCache[path](root);
			n = n[0] ? n[0] : n;
			var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
			return ((v === null || v === undefined || v === '')
					? defaultValue
					: v);
		},

		selectNumber : function(path, root, defaultValue) {
			var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);
			return parseFloat(v);
		},

		is : function(el, ss) {
			if (typeof el == "string") {
				el = document.getElementById(el);
			}
			var isArray = Ext.isArray(el);
			var result = Ext.DomQuery.filter(isArray ? el : [el], ss);
			return isArray ? (result.length == el.length) : (result.length > 0);
		},

		filter : function(els, ss, nonMatches) {
			ss = ss.replace(trimRe, "");
			if (!simpleCache[ss]) {
				simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");
			}
			var result = simpleCache[ss](els);
			return nonMatches ? quickDiff(result, els) : result;
		},

		matchers : [{
					re : /^\.([\w-]+)/,
					select : 'n = byClassName(n, null, " {1} ");'
				}, {
					re : /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
					select : 'n = byPseudo(n, "{1}", "{2}");'
				}, {
					re : /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
					select : 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
				}, {
					re : /^#([\w-]+)/,
					select : 'n = byId(n, null, "{1}");'
				}, {
					re : /^@([\w-]+)/,
					select : 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
				}],

		operators : {
			"=" : function(a, v) {
				return a == v;
			},
			"!=" : function(a, v) {
				return a != v;
			},
			"^=" : function(a, v) {
				return a && a.substr(0, v.length) == v;
			},
			"$=" : function(a, v) {
				return a && a.substr(a.length - v.length) == v;
			},
			"*=" : function(a, v) {
				return a && a.indexOf(v) !== -1;
			},
			"%=" : function(a, v) {
				return (a % v) == 0;
			},
			"|=" : function(a, v) {
				return a && (a == v || a.substr(0, v.length + 1) == v + '-');
			},
			"~=" : function(a, v) {
				return a && (' ' + a + ' ').indexOf(' ' + v + ' ') != -1;
			}
		},

		pseudos : {
			"first-child" : function(c) {
				var r = [], ri = -1, n;
				for (var i = 0, ci; ci = n = c[i]; i++) {
					while ((n = n.previousSibling) && n.nodeType != 1);
					if (!n) {
						r[++ri] = ci;
					}
				}
				return r;
			},

			"last-child" : function(c) {
				var r = [], ri = -1, n;
				for (var i = 0, ci; ci = n = c[i]; i++) {
					while ((n = n.nextSibling) && n.nodeType != 1);
					if (!n) {
						r[++ri] = ci;
					}
				}
				return r;
			},

			"nth-child" : function(c, a) {
				var r = [], ri = -1;
				var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1"
						|| !nthRe2.test(a) && "n+" + a || a);
				var f = (m[1] || 1) - 0, l = m[2] - 0;
				for (var i = 0, n; n = c[i]; i++) {
					var pn = n.parentNode;
					if (batch != pn._batch) {
						var j = 0;
						for (var cn = pn.firstChild; cn; cn = cn.nextSibling) {
							if (cn.nodeType == 1) {
								cn.nodeIndex = ++j;
							}
						}
						pn._batch = batch;
					}
					if (f == 1) {
						if (l == 0 || n.nodeIndex == l) {
							r[++ri] = n;
						}
					} else if ((n.nodeIndex + l) % f == 0) {
						r[++ri] = n;
					}
				}

				return r;
			},

			"only-child" : function(c) {
				var r = [], ri = -1;;
				for (var i = 0, ci; ci = c[i]; i++) {
					if (!prev(ci) && !next(ci)) {
						r[++ri] = ci;
					}
				}
				return r;
			},

			"empty" : function(c) {
				var r = [], ri = -1;
				for (var i = 0, ci; ci = c[i]; i++) {
					var cns = ci.childNodes, j = 0, cn, empty = true;
					while (cn = cns[j]) {
						++j;
						if (cn.nodeType == 1 || cn.nodeType == 3) {
							empty = false;
							break;
						}
					}
					if (empty) {
						r[++ri] = ci;
					}
				}
				return r;
			},

			"contains" : function(c, v) {
				var r = [], ri = -1;
				for (var i = 0, ci; ci = c[i]; i++) {
					if ((ci.textContent || ci.innerText || '').indexOf(v) != -1) {
						r[++ri] = ci;
					}
				}
				return r;
			},

			"nodeValue" : function(c, v) {
				var r = [], ri = -1;
				for (var i = 0, ci; ci = c[i]; i++) {
					if (ci.firstChild && ci.firstChild.nodeValue == v) {
						r[++ri] = ci;
					}
				}
				return r;
			},

			"checked" : function(c) {
				var r = [], ri = -1;
				for (var i = 0, ci; ci = c[i]; i++) {
					if (ci.checked == true) {
						r[++ri] = ci;
					}
				}
				return r;
			},

			"not" : function(c, ss) {
				return Ext.DomQuery.filter(c, ss, true);
			},

			"any" : function(c, selectors) {
				var ss = selectors.split('|');
				var r = [], ri = -1, s;
				for (var i = 0, ci; ci = c[i]; i++) {
					for (var j = 0; s = ss[j]; j++) {
						if (Ext.DomQuery.is(ci, s)) {
							r[++ri] = ci;
							break;
						}
					}
				}
				return r;
			},

			"odd" : function(c) {
				return this["nth-child"](c, "odd");
			},

			"even" : function(c) {
				return this["nth-child"](c, "even");
			},

			"nth" : function(c, a) {
				return c[a - 1] || [];
			},

			"first" : function(c) {
				return c[0] || [];
			},

			"last" : function(c) {
				return c[c.length - 1] || [];
			},

			"has" : function(c, ss) {
				var s = Ext.DomQuery.select;
				var r = [], ri = -1;
				for (var i = 0, ci; ci = c[i]; i++) {
					if (s(ss, ci).length > 0) {
						r[++ri] = ci;
					}
				}
				return r;
			},

			"next" : function(c, ss) {
				var is = Ext.DomQuery.is;
				var r = [], ri = -1;
				for (var i = 0, ci; ci = c[i]; i++) {
					var n = next(ci);
					if (n && is(n, ss)) {
						r[++ri] = ci;
					}
				}
				return r;
			},

			"prev" : function(c, ss) {
				var is = Ext.DomQuery.is;
				var r = [], ri = -1;
				for (var i = 0, ci; ci = c[i]; i++) {
					var n = prev(ci);
					if (n && is(n, ss)) {
						r[++ri] = ci;
					}
				}
				return r;
			}
		}
	};
}();

Ext.query = Ext.DomQuery.select;

Date.precompileFormats = function(s) {
	var formats = s.split('|');
	for (var i = 0, len = formats.length; i < len; i++) {
		Date.createNewFormat(formats[i]);
		Date.createParser(formats[i]);
	}
}

Date
		.precompileFormats("D n/j/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|YmdHis|F d, Y|l, F d, Y|H:i:s|g:i A|g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H|m/d/y|m/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d|Y-m-d H:i:s|d/m/y|d/m/Y|d-m-y|d-m-Y|d/m|d-m|dm|dmy|dmY|Y-m-d|l|D m/d|D m/d/Y|m/d/Y");

Ext.ColorPalette.prototype.tpl = new Ext.XTemplate('<tpl for="."><a href="#" class="color-{.}" hidefocus="on"><em><span style="background:#{.}" unselectable="on">&#160;</span></em></a></tpl>');

Ext.air.FileProvider = function(config) {
	Ext.air.FileProvider.superclass.constructor.call(this);

	this.defaultState = {
		mainWindow : {
			width : 780,
			height : 580,
			x : 10,
			y : 10
		}
	};

	Ext.apply(this, config);
	this.state = this.readState();

	var provider = this;
	air.NativeApplication.nativeApplication.addEventListener('exiting',
			function() {
				provider.saveState();
			});
};

Ext.extend(Ext.air.FileProvider, Ext.state.Provider, {
			file : 'extstate.data',

			readState : function() {
				var stateFile = air.File.applicationStorageDirectory
						.resolvePath(this.file);
				if (!stateFile.exists) {
					return this.defaultState || {};
				}

				var stream = new air.FileStream();
				stream.open(stateFile, air.FileMode.READ);

				var stateData = stream.readObject();
				stream.close();

				return stateData || this.defaultState || {};
			},

			saveState : function(name, value) {
				var stateFile = air.File.applicationStorageDirectory
						.resolvePath(this.file);
				var stream = new air.FileStream();
				stream.open(stateFile, air.FileMode.WRITE);
				stream.writeObject(this.state);
				stream.close();
			}
		});
Ext.air.NativeObservable = Ext.extend(Ext.util.Observable, {
			addListener : function(name) {
				this.proxiedEvents = this.proxiedEvents || {};
				if (!this.proxiedEvents[name]) {
					var instance = this;
					var f = function() {
						var args = Array.prototype.slice.call(arguments, 0);
						args.unshift(name);
						instance.fireEvent.apply(instance, args);
					};
					this.proxiedEvents[name] = f;
					this.getNative().addEventListener(name, f);
				}
				Ext.air.NativeObservable.superclass.addListener.apply(this,
						arguments);
			}
		});

Ext.air.NativeObservable.prototype.on = Ext.air.NativeObservable.prototype.addListener;

Ext.air.NativeWindow = function(config) {
	Ext.apply(this, config);

	this.id = this.id || Ext.uniqueId();

	this.addEvents('close', 'closing', 'move', 'moving', 'resize', 'resizing',
			'displayStateChange', 'displayStateChanging');

	Ext.air.NativeWindow.superclass.constructor.call(this);

	if (!this.instance) {
		var options = new air.NativeWindowInitOptions();
		options.systemChrome = this.chrome;
		options.type = this.type;
		options.resizable = this.resizable;
		options.minimizable = this.minimizable;
		options.maximizable = this.maximizable;
		options.transparent = this.transparent;

		this.loader = window.runtime.flash.html.HTMLLoader.createRootWindow(
				false, options, false);
		this.loader.load(new air.URLRequest(this.file));

		this.instance = this.loader.window.nativeWindow;
	} else {
		this.loader = this.instance.stage.getChildAt(0);
	}

	var provider = Ext.state.Manager;
	var b = air.Screen.mainScreen.visibleBounds;

	var state = provider.get(this.id) || {};
	provider.set(this.id, state);

	var win = this.instance;

	var width = Math.max(state.width || this.width, 100);
	var height = Math.max(state.height || this.height, 100);

	var centerX = b.x + ((b.width / 2) - (width / 2));
	var centerY = b.y + ((b.height / 2) - (height / 2));

	var x = !Ext.isEmpty(state.x, false) ? state.x : (!Ext.isEmpty(this.x,
			false) ? this.x : centerX);
	var y = !Ext.isEmpty(state.y, false) ? state.y : (!Ext.isEmpty(this.y,
			false) ? this.y : centerY);

	win.width = width;
	win.height = height;
	win.x = x;
	win.y = y;

	win.addEventListener('move', function() {
				if (win.displayState != air.NativeWindowDisplayState.MINIMIZED
						&& win.width > 100 && win.height > 100) {
					state.x = win.x;
					state.y = win.y;
				}
			});
	win.addEventListener('resize', function() {
				if (win.displayState != air.NativeWindowDisplayState.MINIMIZED
						&& win.width > 100 && win.height > 100) {
					state.width = win.width;
					state.height = win.height;
				}
			});

	Ext.air.NativeWindowManager.register(this);
	this.on('close', this.unregister, this);

	if (this.minimizeToTray) {
		this.initMinimizeToTray(this.trayIcon, this.trayMenu);
	}

};

Ext.extend(Ext.air.NativeWindow, Ext.air.NativeObservable, {
	chrome : 'standard',
	type : 'normal',
	width : 600,
	height : 400,
	resizable : true,
	minimizable : true,
	maximizable : true,
	transparent : false,

	getNative : function() {
		return this.instance;
	},

	getCenterXY : function() {
		var b = air.Screen.mainScreen.visibleBounds;
		return {
			x : b.x + ((b.width / 2) - (this.width / 2)),
			y : b.y + ((b.height / 2) - (this.height / 2))
		};
	},

	show : function() {
		if (this.trayed) {
			Ext.air.SystemTray.hideIcon();
			this.trayed = false;
		}
		this.instance.visible = true;
	},

	activate : function() {
		this.show();
		this.instance.activate();
	},

	hide : function() {
		this.instance.visible = false;
	},

	close : function() {
		this.instance.close();
	},

	isMinimized : function() {
		return this.instance.displayState == air.NativeWindowDisplayState.MINIMIZED;
	},

	isMaximized : function() {
		return this.instance.displayState == air.NativeWindowDisplayState.MAXIMIZED;
	},

	moveTo : function(x, y) {
		this.x = this.instance.x = x;
		this.y = this.instance.y = y;
	},

	resize : function(width, height) {
		this.width = this.instance.width = width;
		this.height = this.instance.height = height;
	},

	unregister : function() {
		Ext.air.NativeWindowManager.unregister(this);
	},

	initMinimizeToTray : function(icon, menu) {
		var tray = Ext.air.SystemTray;
		tray.setIcon(icon, this.trayTip);
		this.on('displayStateChanging', function(e) {
					if (e.afterDisplayState == 'minimized') {
						e.preventDefault();
						this.hide();
						tray.showIcon();
						this.trayed = true;
					}
				}, this);

		tray.on('click', function() {
					this.activate();
				}, this);

		if (menu) {
			tray.setMenu(menu);
		}
	}
});

Ext.air.NativeWindow.getRootWindow = function() {
	return air.NativeApplication.nativeApplication.openedWindows[0];
};

Ext.air.NativeWindow.getRootHtmlWindow = function() {
	return Ext.air.NativeWindow.getRootWindow().stage.getChildAt(0).window;
};

Ext.air.NativeWindowGroup = function() {
	var list = {};

	return {
		register : function(win) {
			list[win.id] = win;
		},

		unregister : function(win) {
			delete list[win.id];
		},

		get : function(id) {
			return list[id];
		},

		closeAll : function() {
			for (var id in list) {
				if (list.hasOwnProperty(id)) {
					list[id].close();
				}
			}
		},

		each : function(fn, scope) {
			for (var id in list) {
				if (list.hasOwnProperty(id)) {
					if (fn.call(scope || list[id], list[id]) === false) {
						return;
					}
				}
			}
		}
	};
};

Ext.air.NativeWindowManager = new Ext.air.NativeWindowGroup();

Ext.sql.Connection = function(config) {
	Ext.apply(this, config);
	Ext.sql.Connection.superclass.constructor.call(this);

	this.addEvents({
				open : true,
				close : true
			});
};

Ext.extend(Ext.sql.Connection, Ext.util.Observable, {
			maxResults : 10000,
			openState : false,

			open : function(file) {
			},

			close : function() {
			},

			exec : function(sql) {
			},

			execBy : function(sql, args) {
			},

			query : function(sql) {
			},

			queryBy : function(sql, args) {
			},

			isOpen : function() {
				return this.openState;
			},

			getTable : function(name, keyName) {
				return new Ext.sql.Table(this, name, keyName);
			},

			createTable : function(o) {
				var tableName = o.name;
				var keyName = o.key;
				var fs = o.fields;
				if (!Ext.isArray(fs)) {
					fs = fs.items;
				}
				var buf = [];
				for (var i = 0, len = fs.length; i < len; i++) {
					var f = fs[i], s = f.name;
					switch (f.type) {
						case "int" :
						case "bool" :
						case "boolean" :
							s += ' INTEGER';
							break;
						case "float" :
							s += ' REAL';
							break;
						default :
							s += ' TEXT';
					}
					if (f.allowNull === false || f.name == keyName) {
						s += ' NOT NULL';
					}
					if (f.name == keyName) {
						s += ' PRIMARY KEY';
					}
					if (f.unique === true) {
						s += ' UNIQUE';
					}

					buf[buf.length] = s;
				}
				var sql = ['CREATE TABLE IF NOT EXISTS ', tableName, ' (',
						buf.join(','), ')'].join('');
				this.exec(sql);
			}
		});

Ext.sql.Connection.getInstance = function(db, config) {
	if (Ext.isAir) {
		return new Ext.sql.AirConnection(config);
	} else {
		return new Ext.sql.GearsConnection(config);
	}
};
Ext.sql.Table = function(conn, name, keyName) {
	this.conn = conn;
	this.name = name;
	this.keyName = keyName;
};

Ext.sql.Table.prototype = {
	update : function(o) {
		var clause = this.keyName + " = ?";
		return this.updateBy(o, clause, [o[this.keyName]]);
	},

	updateBy : function(o, clause, args) {
		var sql = "UPDATE " + this.name + " set ";
		var fs = [], a = [];
		for (var key in o) {
			if (o.hasOwnProperty(key)) {
				fs[fs.length] = key + ' = ?';
				a[a.length] = o[key];
			}
		}
		for (var key in args) {
			if (args.hasOwnProperty(key)) {
				a[a.length] = args[key];
			}
		}
		sql = [sql, fs.join(','), ' WHERE ', clause].join('');
		return this.conn.execBy(sql, a);
	},

	insert : function(o) {
		var sql = "INSERT into " + this.name + " ";
		var fs = [], vs = [], a = [];
		for (var key in o) {
			if (o.hasOwnProperty(key)) {
				fs[fs.length] = key;
				vs[vs.length] = '?';
				a[a.length] = o[key];
			}
		}
		sql = [sql, '(', fs.join(','), ') VALUES (', vs.join(','), ')']
				.join('');
		return this.conn.execBy(sql, a);
	},

	lookup : function(id) {
		return this.selectBy('where ' + this.keyName + " = ?", [id])[0] || null;
	},

	exists : function(id) {
		return !!this.lookup(id);
	},

	save : function(o) {
		if (this.exists(o[this.keyName])) {
			this.update(o);
		} else {
			this.insert(o);
		}
	},

	select : function(clause) {
		return this.selectBy(clause, null);
	},

	selectBy : function(clause, args) {
		var sql = "select * from " + this.name;
		if (clause) {
			sql += ' ' + clause;
		}
		args = args || {};
		return this.conn.queryBy(sql, args);
	},

	remove : function(clause) {
		this.deleteBy(clause, null);
	},

	removeBy : function(clause, args) {
		var sql = "delete from " + this.name;
		if (clause) {
			sql += ' where ' + clause;
		}
		args = args || {};
		this.conn.execBy(sql, args);
	}
};
Ext.sql.Proxy = function(conn, table, keyName, store, readonly) {
	Ext.sql.Proxy.superclass.constructor.call(this);
	this.conn = conn;
	this.table = this.conn.getTable(table, keyName);
	this.store = store;

	if (readonly !== true) {
		this.store.on('add', this.onAdd, this);
		this.store.on('update', this.onUpdate, this);
		this.store.on('remove', this.onRemove, this);
	}
};

Ext.sql.Proxy.DATE_FORMAT = 'Y-m-d H:i:s';

Ext.extend(Ext.sql.Proxy, Ext.data.DataProxy, {
			load : function(params, reader, callback, scope, arg) {
				if (!this.conn.isOpen()) {
					this.conn.on('open', function() {
								this.load(params, reader, callback, scope, arg);
							}, this, {
								single : true
							});
					return;
				};
				if (this.fireEvent("beforeload", this, params, reader,
						callback, scope, arg) !== false) {
					var clause = params.where || '';
					var args = params.args || [];
					var group = params.groupBy;
					var sort = params.sort;
					var dir = params.dir;

					if (group || sort) {
						clause += ' ORDER BY ';
						if (group && group != sort) {
							clause += group + ' ASC, ';
						}
						clause += sort + ' ' + (dir || 'ASC');
					}

					var rs = this.table.selectBy(clause, args);
					this.onLoad({
								callback : callback,
								scope : scope,
								arg : arg,
								reader : reader
							}, rs);
				} else {
					callback.call(scope || this, null, arg, false);
				}
			},

			onLoad : function(trans, rs, e, stmt) {
				if (rs === false) {
					this.fireEvent("loadexception", this, null, trans.arg, e);
					trans.callback.call(trans.scope || window, null, trans.arg,
							false);
					return;
				}
				var result = trans.reader.readRecords(rs);
				this.fireEvent("load", this, rs, trans.arg);
				trans.callback.call(trans.scope || window, result, trans.arg,
						true);
			},

			processData : function(o) {
				var fs = this.store.fields;
				var r = {};
				for (var key in o) {
					var f = fs.key(key), v = o[key];
					if (f) {
						if (f.type == 'date') {
							r[key] = v ? v
									.format(Ext.sql.Proxy.DATE_FORMAT, 10) : '';
						} else if (f.type == 'boolean') {
							r[key] = v ? 1 : 0;
						} else {
							r[key] = v;
						}
					}
				}
				return r;
			},

			onUpdate : function(ds, record) {
				var changes = record.getChanges();
				var kn = this.table.keyName;
				this.table.updateBy(this.processData(changes), kn + ' = ?',
						[record.data[kn]]);
				record.commit(true);
			},

			onAdd : function(ds, records, index) {
				for (var i = 0, len = records.length; i < len; i++) {
					this.table.insert(this.processData(records[i].data));
				}
			},

			onRemove : function(ds, record, index) {
				var kn = this.table.keyName;
				this.table.removeBy(kn + ' = ?', [record.data[kn]]);
			}
		});
Ext.sql.AirConnection = Ext.extend(Ext.sql.Connection, {

			open : function(db) {
				this.conn = new air.SQLConnection();
				var file = air.File.applicationDirectory.resolvePath(db);
				this.conn.open(file);
				this.openState = true;
				this.fireEvent('open', this);
			},

			close : function() {
				this.conn.close();
				this.fireEvent('close', this);
			},

			createStatement : function(type) {
				var stmt = new air.SQLStatement();
				stmt.sqlConnection = this.conn;
				return stmt;
			},

			exec : function(sql) {
				var stmt = this.createStatement('exec');
				stmt.text = sql;
				stmt.execute();
			},

			execBy : function(sql, args) {
				var stmt = this.createStatement('exec');
				stmt.text = sql;
				this.addParams(stmt, args);
				stmt.execute();
			},

			query : function(sql) {
				var stmt = this.createStatement('query');
				stmt.text = sql;
				stmt.execute(this.maxResults);
				return this.readResults(stmt.getResult());
			},

			queryBy : function(sql, args) {
				var stmt = this.createStatement('query');
				stmt.text = sql;
				this.addParams(stmt, args);
				stmt.execute(this.maxResults);
				return this.readResults(stmt.getResult());
			},

			addParams : function(stmt, args) {
				if (!args) {
					return;
				}
				for (var key in args) {
					if (args.hasOwnProperty(key)) {
						if (!isNaN(key)) {
							var v = args[key];
							if (Ext.isDate(v)) {
								v = v.format(Ext.sql.Proxy.DATE_FORMAT);
							}
							stmt.parameters[parseInt(key)] = v;
						} else {
							stmt.parameters[':' + key] = args[key];
						}
					}
				}
				return stmt;
			},

			readResults : function(rs) {
				var r = [];
				if (rs && rs.data) {
					var len = rs.data.length;
					for (var i = 0; i < len; i++) {
						r[r.length] = rs.data[i];
					}
				}
				return r;
			}
		});
Ext.air.SystemTray = function() {
	var app = air.NativeApplication.nativeApplication;
	var icon, isWindows = false, bitmaps;

	if (air.NativeApplication.supportsSystemTrayIcon) {
		icon = app.icon;
		isWindows = true;
	}

	if (air.NativeApplication.supportsDockIcon) {
		icon = app.icon;
	}

	return {

		setIcon : function(icon, tooltip, initWithIcon) {
			if (!icon) {
				return;
			}
			var loader = new air.Loader();
			loader.contentLoaderInfo.addEventListener(air.Event.COMPLETE,
					function(e) {
						bitmaps = new runtime.Array(e.target.content.bitmapData);
						if (initWithIcon) {
							icon.bitmaps = bitmaps;
						}
					});
			loader.load(new air.URLRequest(icon));
			if (tooltip && air.NativeApplication.supportsSystemTrayIcon) {
				app.icon.tooltip = tooltip;
			}
		},

		bounce : function(priority) {
			icon.bounce(priority);
		},

		on : function(eventName, fn, scope) {
			icon.addEventListener(eventName, function() {
						fn.apply(scope || this, arguments);
					});
		},

		hideIcon : function() {
			if (!icon) {
				return;
			}
			icon.bitmaps = [];
		},

		showIcon : function() {
			if (!icon) {
				return;
			}
			icon.bitmaps = bitmaps;
		},

		setMenu : function(actions, _parentMenu) {
			if (!icon) {
				return;
			}
			var menu = new air.NativeMenu();

			for (var i = 0, len = actions.length; i < len; i++) {
				var a = actions[i];
				if (a == '-') {
					menu.addItem(new air.NativeMenuItem("", true));
				} else {
					var item = menu.addItem(Ext.air.MenuItem(a));
					if (a.menu || (a.initialConfig && a.initialConfig.menu)) {
						item.submenu = Ext.air.SystemTray.setMenu(a.menu
										|| a.initialConfig.menu, menu);
					}
				}

				if (!_parentMenu) {
					icon.menu = menu;
				}
			}

			return menu;
		}
	};
}();

Ext.air.DragType = {
	TEXT : 'text/plain',
	HTML : 'text/html',
	URL : 'text/uri-list',
	BITMAP : 'image/x-vnd.adobe.air.bitmap',
	FILES : 'application/x-vnd.adobe.air.file-list'
};

Ext.apply(Ext.EventObjectImpl.prototype, {
	hasFormat : function(format) {
		if (this.browserEvent.dataTransfer) {
			for (var i = 0, len = this.browserEvent.dataTransfer.types.length; i < len; i++) {
				if (this.browserEvent.dataTransfer.types[i] == format) {
					return true;
				}
			}
		}
		return false;
	},

	getData : function(type) {
		return this.browserEvent.dataTransfer.getData(type);
	}
});

Ext.air.Sound = {
	play : function(file, startAt) {
		var soundFile = air.File.applicationDirectory.resolvePath(file);
		var sound = new air.Sound();
		sound.load(new air.URLRequest(soundFile.url));
		sound.play(startAt);
	}
};

Ext.air.SystemMenu = function() {
	var menu;

	if (air.NativeWindow.supportsMenu
			&& nativeWindow.systemChrome != air.NativeWindowSystemChrome.NONE) {
		menu = new air.NativeMenu();
		nativeWindow.menu = menu;
	}

	if (air.NativeApplication.supportsMenu) {
		menu = air.NativeApplication.nativeApplication.menu;
	}

	function find(menu, text) {
		for (var i = 0, len = menu.items.length; i < len; i++) {
			if (menu.items[i]['label'] == text) {
				return menu.items[i];
			}
		}
		return null;
	}

	return {
		add : function(text, actions, mindex) {

			var item = find(menu, text);
			if (!item) {
				item = menu.addItem(new air.NativeMenuItem(text));
				item.mnemonicIndex = mindex || 0;

				item.submenu = new air.NativeMenu();
			}
			for (var i = 0, len = actions.length; i < len; i++) {
				item.submenu.addItem(actions[i] == '-'
						? new air.NativeMenuItem("", true)
						: Ext.air.MenuItem(actions[i]));
			}
			return item.submenu;
		},

		get : function() {
			return menu;
		}
	};
}();

Ext.air.MenuItem = function(action) {
	if (!action.isAction) {
		action = new Ext.Action(action);
	}
	var cfg = action.initialConfig;
	var nativeItem = new air.NativeMenuItem(cfg.itemText || cfg.text);

	nativeItem.enabled = !cfg.disabled;

	if (!Ext.isEmpty(cfg.checked)) {
		nativeItem.checked = cfg.checked;
	}

	var handler = cfg.handler;
	var scope = cfg.scope;

	nativeItem.addEventListener(air.Event.SELECT, function() {
				handler.call(scope || window, cfg);
			});

	action.addComponent({
				setDisabled : function(v) {
					nativeItem.enabled = !v;
				},

				setText : function(v) {
					nativeItem.label = v;
				},

				setVisible : function(v) {

					nativeItem.enabled = !v;
				},

				setHandler : function(newHandler, newScope) {
					handler = newHandler;
					scope = newScope;
				},

				on : function() {
				}
			});

	return nativeItem;
}
